using Admin2025.Domain.Repositories;
using Admin2025.Infrastructure.Data;
using Dapper;

namespace Admin2025.Infrastructure.Repositories;

public class EfDapRepository<T> : IDapRepository<T> where T : class
{
  // 数据库上下文 依赖注入
  private readonly DapDbContext _db;
  public EfDapRepository(DapDbContext db)
  {
    _db = db;
  }
  public async Task<T> CreateAsync(T entity)
  {
    // typeof(T).Name：获取泛型类型 T 的名称，即数据库表的名称。假设 T 是 User 类型，那么 {typeof(T).Name} 将被替换为 Users（假设表名和类名一致）
    // typeof(T).GetProperties()：获取泛型类型 T 的所有属性（字段）。 
    // Select(p => p.Name)：提取每个属性的名称。
    // Select(p => "@" + p.Name)：为每个属性生成一个参数占位符，例如 @Id 和 @Name。
    // string.Join(",", ...)：将所有属性名称用逗号分隔，生成一个字符串，表示 SQL 查询中的列名。
    string sql = $"INSERT INTO {typeof(T).Name} ({string.Join(",", typeof(T).GetProperties().Select(p => p.Name))}) VALUES({string.Join(",", typeof(T).GetProperties().Select(p => "@" + p.Name))})";
    // _db.Connection：获取数据库连接对象
    // ExecuteAsync：是 Dapper 提供的一个异步方法，用于执行 SQL 查询。 sql：是上面生成的 SQL 插入语句。 entity：是要插入的实体对象
    // transaction: _db.GetCurrentTransaction()：指定当前的数据库事务。如果当前没有事务，则传递 null。
    await _db.Connection.ExecuteAsync(sql, entity, transaction: _db.GetCurrentTransaction());
    return entity;
  }

  public Task DeleteAsync(T entity)
  {
    string sql = $"delete from {typeof(T).Name} where Id = @Id";
    return _db.Connection.ExecuteAsync(sql, new { Id = entity.GetType().GetProperty("Id")?.GetValue(entity) }, transaction: _db.GetCurrentTransaction());
  }

  public async Task<IEnumerable<T>> GetAllAsync()
  {
    string sql = $"SELECT * FROM {typeof(T).Name}";
    return await _db.Connection.QueryAsync<T>(sql, transaction: _db.GetCurrentTransaction());
  }

  public Task<T?> GetByIdAsync(int id)
  {
    string sql = $"SELECT * FROM {typeof(T).Name} WHERE Id = @Id";
    return _db.Connection.QueryFirstOrDefaultAsync<T>(sql, new { Id = id }, transaction: _db.GetCurrentTransaction());
  }

  public Task UpdateAsync(T entity)
  {
    string sql = $"update {typeof(T).Name} set ({string.Join(",", typeof(T).GetProperties().Select(p => p.Name + "= @" + p.Name))} where Id = @Id)";
    return _db.Connection.ExecuteAsync(sql, entity, transaction: _db.GetCurrentTransaction());
  }

  // 通用分页方法
  public async Task<IEnumerable<T>> GetPagedAsync(int pageIndex, int pageSize)
  {
    if (pageIndex < 1) pageIndex = 1;
    if (pageSize < 1) pageSize = 10;

    var tableName = typeof(T).Name;
    var offset = (pageIndex - 1) * pageSize;
    var sql = $@"
            SELECT * FROM [{tableName}]
            ORDER BY Id
            OFFSET @Offset ROWS FETCH NEXT @PageSize ROWS ONLY;
        ";

    var list = await _db.Connection.QueryAsync<T>(sql, new { Offset = offset, PageSize = pageSize }, transaction: _db.GetCurrentTransaction());
    return list;
  }
}